//
// Created by jmm on 17-7-23.
//

#include <jni.h>
#include <stdlib.h>
#include <linux/time.h>
#include <unistd.h>
#include "utilbase.h"
#include "h264_disp.h"
#include <stdio.h>
#include <pthread.h>
#include <android/log.h>

static FILE *inputFile = NULL;
static int mIsRunning = 0;
static pthread_t preview_thread;

#define TAG "myDemo-jni"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__)

void do_preview() {
    long ppos = 0;
    fseek(inputFile, 0L, SEEK_END);
    int end = ftell(inputFile);
    fseek(inputFile, 4, SEEK_SET);
    int cpos = get_nextFrame_position(inputFile, end);

    while(true){
        fseek(inputFile, ppos, SEEK_SET);
        unsigned char * h264_frame = (unsigned char*)calloc(cpos-ppos, sizeof(unsigned char));
        //below code for testing
        fread(h264_frame, 1, cpos-ppos, inputFile);
        LOGD("==================framelen=%d====================", cpos-ppos);
        h264disp_show(h264_frame, cpos-ppos, 0);
        if(cpos == end) break;
        ppos = cpos;
        fseek(inputFile, 4, SEEK_CUR);
        cpos = get_nextFrame_position(inputFile, end);
        free(h264_frame);
    }
    mIsRunning = 0;
}

void *preview_thread_func(void *vptr_args) {
	int result;
	ENTER();
	inputFile = fopen("/storage/emulated/0/testout.h264", "rb");
	if(!inputFile){
        LOGI("open file /storage/emulated/0/testout.h264 failed!!!\n");
        PRE_EXIT();
        pthread_exit(NULL);
	}
	do_preview();
	fclose(inputFile);
	h264disp_uninit();
	PRE_EXIT();
	pthread_exit(NULL);
}


static void nativeSetPreviewDisplay(JNIEnv *env, jobject thiz, jobject jSurface) {
    h264disp_init(env, jSurface);
}

static void nativeStartPreview(JNIEnv *env, jobject thiz) {
	int result = EXIT_FAILURE;
	if (!mIsRunning) {
		mIsRunning = 1;
		result = pthread_create(&preview_thread, NULL, preview_thread_func, NULL);
    }
}

static jint registerNativeMethods(JNIEnv* env, const char *class_name, JNINativeMethod *methods, int num_methods) {
	int result = 0;

	jclass clazz = env->FindClass(class_name);
	if (LIKELY(clazz)) {
		int result = env->RegisterNatives(clazz, methods, num_methods);
		if (UNLIKELY(result < 0)) {
			//LOGE("registerNativeMethods failed(class=%s)", class_name);
		}
	} else {
		//LOGE("registerNativeMethods: class'%s' not found", class_name);
	}
	return result;
}

static JNINativeMethod methods[] = {
	{ "nativeSetPreviewDisplay",		"(Landroid/view/Surface;)V", (void *) nativeSetPreviewDisplay },
    { "nativeStartPreview",				"()V", (void *) nativeStartPreview },
};


jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env;
    if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR;
    }
    // register native methods
    int result = registerNativeMethods(env, "com/example/jmm/myapplication/MainActivity", methods, NUM_ARRAY_ELEMENTS(methods));
	setVM(vm);
    return JNI_VERSION_1_6;
}